<?php

namespace Lib;

use Lib\Base\Config;
use Lib\Base\Request;
use Lib\Base\Validate;
use Lib\Service\RateLimiter;
use Lib\Paas\Login;

class UlinkMain
{
    /**
     * ulink初始化
     *
     * @param string $route
     * @return bool
     */
    public static function init($route = '')
    {
        global $ULINK_INSTANCEID;

        $actId = Request::param('iActId');
        $game = Request::param('game');

        if (!Validate::checkNaturalNum($actId)) {
            recordLog("活动号错误，活动号：" . $actId, __FILE__, __LINE__, LP_ERROR);
            return outputJSON(-1, '活动ID错误！', array('code' => -101));
        }

        $actConfig = array();
        if (ENV != 'test') {
            $actConfig = Config::getActConfig($actId);
            if ($actConfig === false) {
                return outputJson(-1, '系统繁忙，请稍后再试[' . __LINE__ . ']！', array('code' => -102));
            }
            $ULINK_INSTANCEID = $actConfig['INSTANCE_CFG'][0];
        }

        $ULINK_INSTANCEID = empty($ULINK_INSTANCEID) ? LIB_DEFAULT_INSTANCEID : $ULINK_INSTANCEID;

        //生成AmsSerial流水，ulink活动在生成流水号之前，不要掉recordLog函数，没有流水号，上报日志看不到
        if (!Request::getParam('sAmsSerial')) {
            Request::setParam('sAmsSerial', createAmsSerial($ULINK_INSTANCEID, strtoupper($game)));
        }

        recordLog('core_lib_version:' . CORE_LIB_VERSION, __FILE__, __LINE__);

        recordLog('php_sapi_name=' . php_sapi_name(), __FILE__, __LINE__);

        if (php_sapi_name() != 'cli') {
            //get log
            recordLog('$_GET=' . var_export(Request::getParam(), true), __FILE__, __LINE__);

            //post log
            recordLog('$_POST=' . var_export(Request::postParam(), true), __FILE__, __LINE__);

            //cookie log
            recordLog('$_COOKIE=' . var_export(Request::cookieParam(), true), __FILE__, __LINE__);

            //server log
            recordLog('$_SERVER=' . var_export(Request::serverParam(), true), __FILE__, __LINE__);
        }

        //开启活动级别的限流 add by rongzheng 2018/12/4
        if (defined('REQUESTS_PER_SECOND') && REQUESTS_PER_SECOND > 0) {
            $limitKey = 'ulink_request_limiter_' . $actId;
            try {
                $redis = new RateLimiter();
                $ret = $redis->accessLimit($limitKey, 1, REQUESTS_PER_SECOND);
                if ($ret === false) {
                    return outputJson(-1, '活动太火爆，请稍后再来参加！', array('code' => -103));
                }
            } catch (\Exception $e) {
                recordLog("在执行限流时初始化redis对象出现异常，错误信息：" . $e->getMessage(), __FILE__, __LINE__, LP_ERROR);
            }
        }

        if (ENV != 'test') {
            $actConfig = empty($actConfig) ? Config::getActConfig($actId) : $actConfig;

            recordLog("活动配置信息：" . var_export($actConfig, true), __FILE__, __LINE__);

            if ($actConfig === false) {
                return outputJson(-1, '系统繁忙，请稍后再试[' . __LINE__ . ']！', array('code' => -104));
            }

            //校验请求参数中的业务类型、SAPPID等信息
            if (!isset($actConfig['BASE_INFO']['game']) || \strcmp($actConfig['BASE_INFO']['game'], $game) !== 0) {
                return outputJson(-1, '系统繁忙，请稍后再试[' . __LINE__ . ']！', array('code' => -105));
            }
            //校验SAPPID
            if (!isset($actConfig['BASE_INFO']['sAppId']) || \strcmp($actConfig['BASE_INFO']['sAppId'], ULINK_SAPPID) !== 0) {
                return outputJson(-1, '系统繁忙，请稍后再试[' . __LINE__ . ']！', array('code' => -106));
            }

            //活动如果被强制下线，则给出对应提示
            if (!isset($actConfig['BASE_INFO']['status']) || !in_array($actConfig['BASE_INFO']['status'], ['0', '1'])) {
                return outputJson(-1, '活动太火爆，请稍后再试！', array('code' => -107));
            } else {
                if ($actConfig['BASE_INFO']['status'] == 1) {
                    //判断活动是否在有效期内
                    $nowTime = date('Y-m-d H:i:s');

                    //紧急停用
                    if (strtotime($nowTime) >= strtotime('2020-04-04 00:00:00') && strtotime($nowTime) < strtotime('2020-04-05 00:00:00')) {
                        return outputJson(-1, '为深切哀悼在抗击新冠肺炎斗争中牺牲烈士和逝世同胞，4月4日00:00-24:00期间，腾讯游戏旗下所有产品(含中国大陆和中国港澳台区域)将停服。愿逝者安息，愿生者奋发，愿祖国昌盛。', array('code' => -109));
                    }

                    if (!isset($actConfig['BASE_INFO']['sday']) || !isset($actConfig['BASE_INFO']['eday'])) {
                        recordLog("活动配置文件中缺少sday或者eday,请检查配置文件！", __FILE__, __LINE__, LP_ERROR);
                        return outputJson(-1, '系统繁忙，请稍后再试[' . __LINE__ . ']！', array('code' => -108));
                    }
                    //校验活动时间
                    if ($nowTime < $actConfig['BASE_INFO']['sday']) {
                        return outputJson(-1, '活动还未开始，敬请期待！', array('code' => -109));
                    }
                    if ($actConfig['BASE_INFO']['eday'] < $nowTime) {
                        return outputJson(-1, '活动已经结束！', array('code' => -110));
                    }
                }
            }
        }

        $login = null;
        //强制开启登录校验
        recordLog('NO_CHECK_LOGIN=' . var_export(NO_CHECK_LOGIN, true) . ', $route=' . var_export($route, true), __FILE__, __LINE__);

        if (!defined('NO_CHECK_LOGIN') || !in_array($route, NO_CHECK_LOGIN)) {
            $login = new Login();
            if (!$login->checkLogin()) {
                return outputJson(-1, '登录态失效，请重新登录！', array('code' => -111));
            }
        }

        //白名单校验
        if (ENV == 'pre' || (ENV == 'pro' && $actConfig['BASE_INFO']['status'] == '0')) {
            //不需要登录校验的模块不进行白名单校验
            if (!defined('NO_CHECK_LOGIN') || !in_array($route, NO_CHECK_LOGIN)) {
                $login = is_null($login) ? new Login() : $login;
                if (!$login->checkInWhite()) {

                    if (isset($actConfig['NOTWHITEMSG_CFG'][0]) && $actConfig['NOTWHITEMSG_CFG'][0] != '') {
                        $whiteMsg = $actConfig['NOTWHITEMSG_CFG'][0];
                    } else {
                        $whiteMsg = '活动暂未开放，敬请期待！';
                    }

                    return outputJson(-1, $whiteMsg, array('code' => -112));
                }
            }
        }
        return true;
    }
}
